package com.xx.text.tool.encipher

import android.os.Build
import android.util.Base64
import android.util.Log
import androidx.annotation.RequiresApi
import com.xx.text.tool.encipher.Base64Utils.encode
import java.nio.charset.StandardCharsets
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec

object AESUtils {
    private const val KEY_ALGORITHM = "AES"
    private const val DEFAULT_CIPHER_ALGORITHM = "AES/GCM/NoPadding"
    private const val algorithm = "SHA-256"
    const val seed = "EBD0B5D2-F4E7-453A-9E16-01AE8F6E2977"


    fun createRandomKey(): SecretKeySpec {
        val random = SecureRandom()
        val encryptionKey = ByteArray(16)
        random.nextBytes(encryptionKey)
        return SecretKeySpec(encryptionKey, "AES")
    }

    /**
     * aes
     *
     * @param sKey key
     * @param sSrc data
     * @return
     * @throws Exception
     */
    @RequiresApi(Build.VERSION_CODES.KITKAT)
    @Throws(Exception::class)
    fun aesDecrypt(sKey: SecretKeySpec?, sSrc: String?): String? {
        return try {
            val content: ByteArray = Base64.decode(sSrc, Base64.DEFAULT)
            require(content.size >= 12 + 16)
            val params = GCMParameterSpec(128, content, 0, 12)
            try {
                val cipher: Cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM)
                cipher.init(Cipher.DECRYPT_MODE, sKey, params)
                val decryptData: ByteArray = cipher.doFinal(content, 12, content.size - 12)
                return String(decryptData, StandardCharsets.UTF_8)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            null
        } catch (ex: Exception) {
            throw ex
        }
    }

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    @Throws(NoSuchAlgorithmException::class)
    fun getSecretKeySpec(seed: String): SecretKeySpec? {
        val keyGenerator: KeyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM)
        val secureRandom: SecureRandom = SecureRandom.getInstance("SHA1PRNG")
        secureRandom.setSeed(seed.toByteArray(StandardCharsets.UTF_8))
        keyGenerator.init(256, secureRandom)
        val secretKey: SecretKey = keyGenerator.generateKey()
        val encode: ByteArray = secretKey.encoded
        val base64 = encode(encode)
        Log.d("OkHttp", "base64 key = $base64")
        return SecretKeySpec(encode, KEY_ALGORITHM)
    }

    /**
     * AES
     *
     * @param content
     * @param encryptPass
     * @return
     */
    @RequiresApi(Build.VERSION_CODES.KITKAT)
    fun encrypt(content: String, encryptPass: SecretKeySpec?): String? {
        try {
            val cipher: Cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM)
            val iv: ByteArray
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                iv = ByteArray(12)
                SecureRandom().nextBytes(iv)
                cipher.init(Cipher.ENCRYPT_MODE, encryptPass, GCMParameterSpec(128, iv))
            } else {
                cipher.init(Cipher.ENCRYPT_MODE, encryptPass)
                iv = cipher.iv
                assert(iv.size == 12)
            }
            val encryptData: ByteArray = cipher.doFinal(content.toByteArray())
            assert(encryptData.size == content.toByteArray().size + 16)
            val message = ByteArray(12 + content.toByteArray().size + 16)
            System.arraycopy(iv, 0, message, 0, 12)
            System.arraycopy(encryptData, 0, message, 12, encryptData.size)
            return encode(message)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

}